/*
  databind混入，是、给业务管理列表组件使用的。封装了数据加载、查询、排序、多选等一系列操作，简化业务组件的代码量。
  1，可混入到PageableTable组件
  2，可混入到AssetTable组件
*/
import { on, off, isArray, isObject } from '@neu/biz-core/utils/utils'
import { debounce, isEmpty } from '@neu/biz-core/utils'

export default {
  props: {
    // 该属性控制列表组件（视图）是否用于第三方组件的选择用。会影响到操作按钮的显示，列表高度等
    forSelection: {
      type: Boolean,
      default: false
    },
    dialogFixHeight: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      r: '', // 列表翻页查询api，符合分页查询接口规范
      d: '', // 删除列表项api，带一个参数
      ds: '',
      currentPage: 1, // 翻页控件当前页码
      totalElements: 0, // 符合查询条件的所有记录总和
      pageSize: 20, // 一页显示记录数
      tableSort: { dataIndex: 'id', order: 'desc' }, // 排序
      searchObj: {}, // 查询条件
      loading: false, // 查询时，显示加载中
      insideTableData: [], // 列表数据
      insideColumns: [], // 列定义
      selections: [], // 多选时，选择的记录项
      tableHeight: 0, // table的高度，数据加载、页面高度等变化会监听改变table的高度
      filterItems: [], // 记录筛选项，用于在特定位置显示当前已使用的选项
      $_resizeHandler: null // 自适应高度处理函数
    }
  },
  created: function() {
    // 拉取列表数据
    this.filter(this.$route.params)
  },
  mounted: function() {
    // 初始化页面改变监听
    this.$nextTick(function() {
      this.initListener()
      this.$_resizeHandler()
    })
  },
  methods: {
    // 拉取列表数据，符合前后台接口规范
    fetch: function() {
      this.loading = true
      this.r(this.getQuery()).then(response => {
        const result = response.data
        const data = this.responseFormatter(result)
        this.insideTableData = data // Object.freeze(data)
        this.loading = false

        const pageable = response.pageable
        this.totalElements = pageable && pageable.totalElements ? pageable.totalElements : 0
      }).catch(err => {
        console.error(err)
        this.loading = false
      })
    },
    // 搜索。 search支持两种格式的搜索想定义
    // 1，{s_name: '张三', s_dead: true}
    // 2. {s_name: {label: '姓名', value: '张三'}}
    filter: function(search) {
      let complexSearch = false
      const searchObj = Object.assign({}, search)
      if (Object.keys(searchObj).some(k => isObject(searchObj[k]))) {
        complexSearch = true
      }
      // 清理无效查询项
      for (const k in searchObj) {
        if (complexSearch) {
          if (isEmpty(searchObj[k].value)) delete searchObj[k]
        } else {
          if (isEmpty(searchObj[k])) delete searchObj[k]
        }
      }

      let _searchObj = {}
      if (complexSearch) {
        for (const k in searchObj) {
          _searchObj[k] = searchObj[k].value
        }
        // 记录筛选项
        this.filterItems = Object.keys(searchObj).filter(key => !(searchObj[key].hidden === true)).map(key => { return { k: key, v: searchObj[key] } })
      } else {
        _searchObj = Object.assign({}, searchObj)
      }
      this.searchObj = _searchObj
      this.currentPage = 1
      this.refresh()
    },
    // 重新获取数据
    refresh: function() {
      setTimeout(() => this.fetch(), 1)
    },
    // 构造查询条件。符合前后台接口规范
    getQuery: function() {
      const _this = this
      return Object.assign({
        page: _this.currentPage - 1,
        size: _this.pageSize,
        sort: _this.tableSort.dataIndex + ',' + _this.tableSort.order
      }, this.searchObj)
    },
    // 返回数据格式化。在API返回不符合规范的原始数据后，可以自定义一个格式转换函数
    responseFormatter: function(i) {
      return i
    },
    // 删除数据项。支持批量和单各删除。
    remove: function(id) {
      if (isArray(id)) {
        if (id.length > 1) {
          this.batchRemove(id.map(it => it.id))
          return
        } else if (id.length === 1) {
          id = id[0].id
        } else {
          this.$message({
            type: 'warning',
            message: '请选择操作数据!'
          })
          return
        }
      }
      this.$confirm(this.getConfirmContent(), '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.d(id).then(response => {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.refresh()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    batchRemove: function(ids) {
      this.$confirm(this.getConfirmContent(), '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.ds(ids).then(response => {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.refresh()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 页面可自定义确认文字
    getConfirmContent() {
      return '确定要删除吗？'
    },
    // 接收PagebaleTable和AssetTable的翻页事件
    onPageChange: function(pageObj) {
      this.currentPage = pageObj.page
      this.pageSize = pageObj.limit
      this.refresh()
    },
    // 接收PagebaleTable和AssetTable的排序事件
    onSortChange: function(sortObj) {
      if (sortObj.order === null) {
        this.tableSort.dataIndex = 'id'
        this.tableSort.order = 'desc'
      } else {
        this.tableSort.dataIndex = sortObj.prop
        this.tableSort.order = sortObj.order === 'descending' ? 'desc' : 'asc'
      }
      this.refresh()
    },
    // 接收PagebaleTable和AssetTable的多选事件
    onSelectionChange(val) {
      this.selections = isArray(val) ? val : [val]
    },
    onResize() {
      this.$_resizeHandler()
    },
    // 清空多选项，根据类名找到element-ui的table组件，调用element-ui的table api清空
    // 如果结构不符合要求，可以在页面重写该方法
    clearSelection() {
      this.$children.filter(it => it.$el.classList.contains('fixed-table-table')).forEach(it => {
        it.$refs.pageableTable.clearSelection()
      })
    },
    initListener() {
      this.$_resizeHandler = debounce(() => {
        const _this = this
        // 页面头高度 50
        // .app-container padding上下总和 16
        // document.querySelector('.table-app-container .fixed-table-filter').offsetHeight
        // document.querySelector('.table-app-container .fixed-table-actionbar')
        // 翻页组件高度 42
        // .fixed-table padding上下和边框 18
        const tableFilterSel = document.querySelector('.table-app-container .fixed-table-filter')
        const tableFilterHeight = tableFilterSel ? tableFilterSel.offsetHeight : 0

        const tableActionbarSel = document.querySelector('.table-app-container .fixed-table-actionbar')
        const tableActionbarHeight = tableActionbarSel ? tableActionbarSel.offsetHeight : 0

        const assetTableBarSel = document.querySelector('.table-app-container .asset-table-bar')
        const assetTableBarHeight = assetTableBarSel ? assetTableBarSel.offsetHeight : 0

        const filterTreeSel = document.querySelector('.table-app-container .filter-tree')
        if (filterTreeSel) {
          filterTreeSel.style.height = (window.innerHeight - 50 - 16) + 'px'
        }

        if (!_this.forSelection) {
          if (_this.dialogFixHeight === 0) {
            _this.tableHeight = window.innerHeight - 50 - 16 - tableFilterHeight - assetTableBarHeight - tableActionbarHeight - 42 - 18
          } else {
            _this.tableHeight = window.innerHeight * 0.9 - _this.dialogFixHeight - tableFilterHeight - assetTableBarHeight - tableActionbarHeight
          }
        } else {
          _this.tableHeight = window.innerHeight - 16 - tableFilterHeight - assetTableBarHeight - tableActionbarHeight - 42 - 18 - window.innerHeight * 0.2 - 120
        }
      }, 300)

      on(window, 'resize', this.$_resizeHandler)
    }
    // getEleTable() {
    //   return this.$refs.pageableTable
    // }
  },
  beforeDestroy() {
    off(window, 'resize', this.onResize)
  }
}
